package com.ruoyi.linxi.business;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.linxi.constant.NumberConstant;
import com.ruoyi.linxi.constant.SymbolConstant;
import com.ruoyi.linxi.entry.Account;
import com.ruoyi.linxi.entry.Invoice;
import com.ruoyi.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Title TODO
 * @Description TODO
 * @Author CAI ZHAI
 * @Date 2021/9/18 10:44
 **/
@Slf4j
public class AccountUtil{
    
    public static void changeInvoiceRoomNumber(List<Invoice> invoiceList){
        for(Invoice invoice : invoiceList){
            String fh = invoice.getFh().trim();
            /*if(fh.equals("18-905")){
                log.info("");
            }*/
            invoice.setFh(changeRoomNumber(fh));
        }
    }
    public static void changeAccountRoomNumber(List<Account> accountList){
        for(Account account : accountList){
            String fh = account.getJhdfh().trim();
            account.setXtfh(changeRoomNumber(fh));
        }
    }
    
    private static String changeRoomNumber(String fh){
        if(StringUtils.isNotBlank(fh)){
            if(fh.contains(SymbolConstant.DUN_H)){
                fh = fh.replace(SymbolConstant.DUN_H, SymbolConstant.XG);
            }
            if(fh.contains(SymbolConstant.XG)){
                String[] split = fh.split(SymbolConstant.XG);
                return changeToNumberAll(split[0])+ SymbolConstant.XG+ changeToNumberAll(split[1]);
            }
    
            return changeToNumberAll(fh);
        }
        
        return "";
    }
    
    //转换房号，入口
    private static String changeToNumberAll(String fh){
        String[] split = fh.split(SymbolConstant.HG);
        int length = split.length;
        if(length==0 || length==1){
            return fh;
        }else if(length==2){
            String three = split[0] + SymbolConstant.HG + "1" + SymbolConstant.HG + split[1];
            return changeToFourNumber(three);
        }else if(length==3){
            return changeToFourNumber(fh);
        }else if(length==4){
            return fh;
        }else if(length==9){
            return split[5] + SymbolConstant.HG + addZeor(split[6]) + SymbolConstant.HG +split[7] + SymbolConstant.HG +split[8];
        }else {
            log.error("changeRoomNumber转换房号失败："+ fh);
            return "";
        }
    }
    
    // 7-1-301 转 07-01- 03 -01
    private static String changeToFourNumber(String fh){
        String[] split = fh.split(SymbolConstant.HG);
        String OneTwoStr = addZeor(split[0]) + SymbolConstant.HG + addZeor(split[1]);
    
        String three = split[2];
        char[] chars = three.toCharArray();
        if(chars.length==3){
            three =  "0" + three;
            return OneTwoStr + SymbolConstant.HG + toTwoStr(three);
        }else if(chars.length==4){
            return OneTwoStr + SymbolConstant.HG + toTwoStr(three);
        }else {
            log.error("changeToFourNumber转换房号失败："+ fh);
            return "";
        }
    }
    
    // 7-1-0301 的 0301 转 03-01
    private static String toTwoStr(String fh){
        return fh.substring(0,2) + SymbolConstant.HG + fh.substring(2,4);
    }
    
    // 7-1-0301 的 0301 转 03-01
    private static String addZeor(String str){
        char[] zeroChars = str.toCharArray();
        if(zeroChars.length==1){
            return  "0" + str;
        }
        return str;
    }
    
    //计算发票与银行台账差额
    public static void mergeInvoice(List<Invoice> invoiceList,List<Account> accountList){
        for(Invoice invoice : invoiceList){
            boolean flag = false;
            BigDecimal accountSum = new BigDecimal(0);
            String fh = invoice.getFh();
            if(StringUtils.isNotBlank(fh)){
                for(Account account : accountList){
                    String xtfh = account.getXtfh();
                    if(fh.equals(xtfh)){
                        accountSum = accountSum.add(new BigDecimal(account.getJyje())); //账单出现相同房号，加起来
                        flag = true;
                        break;
                    }
                }
            }
        
            if(flag){ //找到房号，开始对账
                reconciliationInvoiveRoom(invoice, accountSum);
            }else {  //找不到房号，去带斜杠的找
                boolean notRoomFlag = false;
                for(Account account : accountList){
                    if(account.getXtfh().contains(invoice.getFh())){
                        accountSum = new BigDecimal(account.getJyje());
                        notRoomFlag = true;
                    }
                }
                if(notRoomFlag){
                    reconciliationInvoiveRoom(invoice, accountSum);
                }
            }
        }
    }
    
    //银行账单含斜杠的，发票加起来
    private static void invoiceAddIfAccountXg(List<Invoice> invoiceList,List<Account> accountList){
        for(Account account : accountList){
            String xtfh = account.getXtfh();
            if(xtfh.contains(SymbolConstant.XG)){
                String[] split = xtfh.split(SymbolConstant.XG);
                if(split.length==2){
                    invoiceAdd(split, invoiceList);
                }else {
                    log.error("reconciliationRoomNot房号包含多个斜杠："+xtfh);
                }
            }
        }
    }
    
    //对斜杠数据求和
    private static void invoiceAdd(String[] split, List<Invoice> invoiceList){
        BigDecimal sum = new BigDecimal(0);
        Invoice invoice0 = null;
        Invoice invoice1 = null;
    
        String fh0 = split[0];
        String fh1 = split[1];
        for(Invoice invoice : invoiceList){
            if(fh0.equals(invoice.getFh())){
                sum = sum.add(new BigDecimal(invoice.getHj()));
                invoice0 = invoice;
            }
            if(fh1.equals(invoice.getFh())){
                sum = sum.add(new BigDecimal(invoice.getHj()));
                invoice1 = invoice;
            }
        }
        
        if(invoice0!=null){
            invoice0.setHj(NumberUtil.bigDecimalToStr(sum));
        }
        if(invoice1!=null){
            invoice1.setHj(NumberUtil.bigDecimalToStr(sum));
        }
    }
    
    
    //找不到房号，去带斜杠的找
    /*private static void reconciliationRoomNot(Invoice invoice, List<Invoice> invoiceList,List<Account> accountList){
        String fh = invoice.getFh();
        if(!fh.contains(SymbolConstant.XG)){
            for(Account account : accountList){
                String jhdfh = account.getJhdfh();
                if(jhdfh.contains(fh)){
                    String[] split = jhdfh.split(SymbolConstant.XG);
                    if(split.length==2){
                    
                    }else {
                        log.error("reconciliationRoomNot房号包含多个斜杠："+fh);
                    }
                }
            }
        }
    }*/
    
    //找到房号，开始对账
    private static void reconciliationInvoiveRoom(Invoice invoice, BigDecimal accountSum){
        invoice.setYhzd(NumberUtil.bigDecimalToStr(accountSum));
        BigDecimal subtract = accountSum.subtract(new BigDecimal(invoice.getHj()));
        if(subtract.compareTo(new BigDecimal(0))>=0){   //正常来讲，银行账单比发票多垃圾费
            BigDecimal[] bigDecimals = subtract.divideAndRemainder(NumberConstant.LJF);
            BigDecimal bs = bigDecimals[0]; //倍数
            BigDecimal ys = bigDecimals[1]; //余数
            if(bs.compareTo(NumberConstant.LJ_COUNT)<=0 && ys.compareTo(new BigDecimal(0))==0){ //对平
                invoice.setLjp(NumberUtil.bigDecimalToStr(subtract));
                invoice.setCe("0");
                invoice.setDp(SymbolConstant.G);
            }else if(bs.compareTo(NumberConstant.LJ_COUNT)<=0){ //近似平
                if(subtract.abs().compareTo(new BigDecimal(4))<0){ //差值太小，无垃圾票
                    invoice.setLjp("0");
                    invoice.setCe(NumberUtil.bigDecimalToStr(subtract));
                    invoice.setDp(SymbolConstant.GG);
                }else {
                    if(ys.abs().compareTo(new BigDecimal(3))>0){ //正数垃圾票
                        BigDecimal ljf = NumberConstant.LJF.multiply(bs.add(new BigDecimal(1)));
                        invoice.setLjp(NumberUtil.bigDecimalToStr(ljf));
                        BigDecimal jsCe = subtract.subtract(ljf);
                        invoice.setCe(NumberUtil.bigDecimalToStr(jsCe));
                        invoice.setDp(SymbolConstant.GG);
                    }else{ //负数垃圾票
                        BigDecimal ljf = NumberConstant.LJF.multiply(bs);
                        invoice.setLjp(NumberUtil.bigDecimalToStr(ljf));
                        invoice.setCe(NumberUtil.bigDecimalToStr(ys));
                        invoice.setDp(SymbolConstant.GG);
                    }
                }
            }else { //不平
                invoice.setCe(NumberUtil.bigDecimalToStr(subtract));
            }
        }else {
            if(subtract.compareTo(new BigDecimal(-1))>0){   //近似平
                invoice.setLjp("0");
                invoice.setCe(NumberUtil.bigDecimalToStr(subtract));
                invoice.setDp(SymbolConstant.GG);
            }else {
                invoice.setLjp("0");
                invoice.setCe(NumberUtil.bigDecimalToStr(subtract));
            }
        }
    }
    
    //以银行为准
    private static void reconciliationAccountRoom(Account account, BigDecimal invoiceSum){
        account.setFpJshj(NumberUtil.bigDecimalToStr(invoiceSum));
        BigDecimal subtract = new BigDecimal(account.getJyje()).subtract(invoiceSum);
        if(subtract.compareTo(new BigDecimal(0))>=0){   //正常来讲，银行账单比发票多垃圾费
            BigDecimal[] bigDecimals = subtract.divideAndRemainder(NumberConstant.LJF);
            BigDecimal bs = bigDecimals[0]; //倍数
            BigDecimal ys = bigDecimals[1]; //余数
            if(bs.compareTo(NumberConstant.LJ_COUNT)<=0 && ys.compareTo(new BigDecimal(0))==0){ //对平
                account.setLjp(NumberUtil.bigDecimalToStr(subtract));
                account.setCe("0");
                account.setDp(SymbolConstant.G);
            }else if(bs.compareTo(NumberConstant.LJ_COUNT)<=0){ //近似平
                if(subtract.abs().compareTo(new BigDecimal(4))<0){ //差值太小，无垃圾票
                    account.setLjp("0");
                    account.setCe(NumberUtil.bigDecimalToStr(subtract));
                    account.setDp(SymbolConstant.GG);
                }else {
                    if(ys.abs().compareTo(new BigDecimal(3))>0){ //正数垃圾票
                        BigDecimal ljf = NumberConstant.LJF.multiply(bs.add(new BigDecimal(1)));
                        account.setLjp(NumberUtil.bigDecimalToStr(ljf));
                        BigDecimal jsCe = subtract.subtract(ljf);
                        account.setCe(NumberUtil.bigDecimalToStr(jsCe));
                        account.setDp(SymbolConstant.GG);
                    }else{ //负数垃圾票
                        BigDecimal ljf = NumberConstant.LJF.multiply(bs);
                        account.setLjp(NumberUtil.bigDecimalToStr(ljf));
                        account.setCe(NumberUtil.bigDecimalToStr(ys));
                        account.setDp(SymbolConstant.GG);
                    }
                }
            }else { //不平
                account.setCe(NumberUtil.bigDecimalToStr(subtract));
            }
        }else {
            if(subtract.compareTo(new BigDecimal(-1))>0){   //近似平
                account.setLjp("0");
                account.setCe(NumberUtil.bigDecimalToStr(subtract));
                account.setDp(SymbolConstant.GG);
            }else {
                account.setLjp("0");
                account.setCe(NumberUtil.bigDecimalToStr(subtract));
            }
        }
    }
    
    //发票出现相同房号，加起来
    private static void invoiceAddTheSameFh(List<Invoice> invoiceList){
        Map<String,Invoice> invoiceMap = new HashMap<>();
        for(Invoice invoice : invoiceList){
            String fh = invoice.getFh();
            if(org.apache.commons.lang3.StringUtils.isNotBlank(fh)){
                Invoice invoiceM = invoiceMap.get(fh);
                if(invoiceM==null){
                    invoiceMap.put(fh, invoice);
                }else {
                    String hj = invoiceM.getHj();
                    String hj1 = invoice.getHj();
                    invoiceM.setHj(NumberUtil.str1AndStr2(hj, hj1));
                    invoiceMap.put(fh, invoiceM);
                }
            }
        }
        for(Invoice invoice : invoiceList){
            String fh = invoice.getFh();
            if(StringUtils.isNotBlank(fh)){
                Invoice invoiceM = invoiceMap.get(fh);
                if(invoiceM!=null){
                    invoice.setHj(invoiceM.getHj());
                }
            }
        }
    }
    
    //银行
    private static void accountAddTheSameFh(List<Account> accountList){
        Map<String,Account> accountMap = new HashMap<>();
        for(int i = accountList.size()-1; i>0 ; i--){
            Account account = accountList.get(i);
            String fh = account.getXtfh();
            if(StringUtils.isNotBlank(fh)){
                Account accountM = accountMap.get(fh);
                if(accountM==null){
                    accountMap.put(fh, account);
                }else {
                    String hj = accountM.getJyje();
                    String hj1 = account.getJyje();
                    accountM.setJyje(NumberUtil.str1AndStr2(hj, hj1));
                    accountMap.put(fh, accountM);
                    //log.warn("accountAddTheSameFh房号重复：" + fh);
                    accountList.remove(i);
                }
            }
        }
        
        /*for(Account account : accountList){
            String fh = account.getXtfh();
            if(StringUtils.isNotBlank(fh)){
                Account invoiceM = accountMap.get(fh);
                if(invoiceM!=null){
                    account.setJyje(invoiceM.getJyje());
                }
            }
        }*/
    }
    
    public static void main(String[] args){
        BigDecimal bigDecimal = new BigDecimal(15);
        BigDecimal bigDecimal1 = new BigDecimal(4);
        BigDecimal[] bigDecimals = bigDecimal.divideAndRemainder(bigDecimal1);
        System.out.println();
    }
    
    //导出Excel
    public static void exportInvoiceAccountExcel(String oldExcel, String newExcel,
                                                 List<Invoice> invoiceList,List<Account> accountList){
        try{
            File oldFile = new File(oldExcel);
            File newFile = new File(newExcel);
            //FileUtils.copyFile(new File(oldExcel), newFile);
    
            InputStream is = new FileInputStream(oldFile);
            XSSFWorkbook wb = new XSSFWorkbook(is);
            XSSFSheet sheet = wb.getSheetAt(0);
            for(int i = 0; i<invoiceList.size(); i++){
                Invoice invoice = invoiceList.get(i);
                int rowIndex = i+1;
                XSSFRow row = sheet.getRow(rowIndex);
                XSSFCell cell2 = row.createCell(2);
                XSSFCell cell3 = row.createCell(3);
                XSSFCell cell4 = row.createCell(4);
                XSSFCell cell5 = row.createCell(5);
                cell2.setCellValue(invoice.getYhzd());
                cell3.setCellValue(invoice.getLjp());
                cell4.setCellValue(invoice.getCe());
                cell5.setCellValue(invoice.getDp());
            }
    
            XSSFSheet sheet1 = wb.getSheetAt(2);
            for(int i = 0; i<accountList.size(); i++){
                Account account = accountList.get(i);
                int rowIndex = i+1;
                XSSFRow row = sheet1.createRow(rowIndex);
                XSSFCell cell0 = row.createCell(0);
                XSSFCell cell1 = row.createCell(1);
                XSSFCell cell2 = row.createCell(2);
                XSSFCell cell3 = row.createCell(3);
                XSSFCell cell4 = row.createCell(4);
                XSSFCell cell5 = row.createCell(5);
                XSSFCell cell6 = row.createCell(6);
                cell0.setCellValue(account.getJyje());
                cell1.setCellValue(account.getJhdfh());
                cell2.setCellValue(account.getXtfh());
                cell3.setCellValue(account.getFpJshj());
                cell4.setCellValue(account.getLjp());
                cell5.setCellValue(account.getCe());
                cell6.setCellValue(account.getDp());
            }
    
            OutputStream newIs = new FileOutputStream(newFile);
            wb.write(newIs);
            wb.close();
            newIs.close();
            System.out.println("finish！");
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    
    //以银行为准
    public static void mergeAccount(List<Invoice> invoiceList,List<Account> accountList){
        for(Account account : accountList){
            boolean flag = false;
            BigDecimal invoiceSum = new BigDecimal(0);
            String fh = account.getXtfh();
            if(StringUtils.isNotBlank(fh)){
                for(Invoice invoice : invoiceList){
                    String xtfh = invoice.getFh();
                    if(fh.equals(xtfh)){
                        invoiceSum = invoiceSum.add(new BigDecimal(invoice.getHj())); //账单出现相同房号，加起来(不用加，在前面已经加过一次了)
                        flag = true;
                        break;
                    }
                }
            }
        
            if(flag){ //找到房号，开始对账
                reconciliationAccountRoom(account, invoiceSum);
            }else {  //找不到房号，去带斜杠的找
                boolean notRoomFlag = false;
                for(Invoice invoice : invoiceList){
                    if(account.getXtfh().contains(invoice.getFh())){
                        invoiceSum = new BigDecimal(invoice.getHj());
                        notRoomFlag = true;
                    }
                }
                if(notRoomFlag){
                    reconciliationAccountRoom(account, invoiceSum);
                }
            }
        }
    }
    
    //处理金额
    public static void addMoney(List<Invoice> invoiceList,List<Account> accountList){
        //发票出现相同房号，金额加起来
        invoiceAddTheSameFh(invoiceList);
        //银行出现相同房号，金额加起来
        accountAddTheSameFh(accountList);
        //银行账单含斜杠的，发票加起来
        invoiceAddIfAccountXg(invoiceList, accountList);
    }
    
    
}
